package com.insis.manager;

import com.insis.annotation.RpcServer;
import com.insis.annotation.RpcServerScan;
import com.insis.message.RpcResponseMessage;
import com.insis.protocol.MessageCodecSharable;
import com.insis.protocol.ProcotolFrameDecoder;
import com.insis.registry.NacosServerRegistry;
import com.insis.server.handler.RpcRequestMessageHandler;
import com.insis.utils.PackageScanUtils;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.util.Set;

@Slf4j
public class RpcServerManager {

    protected NacosServerRegistry nacosServerRegistry;
    protected String ip;
    protected int port;



    public RpcServerManager(String ip, int port){
        nacosServerRegistry = new NacosServerRegistry();
        this.ip = ip;
        this.port = port;
        autoRegister();
    }

    public void start(){
        NioEventLoopGroup boss = new NioEventLoopGroup();
        NioEventLoopGroup worker = new NioEventLoopGroup();
        LoggingHandler LOGGING_HANDLER = new LoggingHandler(LogLevel.DEBUG);
        MessageCodecSharable MESSAGE_CODEC = new MessageCodecSharable();
        RpcRequestMessageHandler RPC_HANDLER = new RpcRequestMessageHandler();
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.channel(NioServerSocketChannel.class);
            serverBootstrap.group(boss, worker);
            serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) throws Exception {
                    ch.pipeline().addLast(new ProcotolFrameDecoder());
                    ch.pipeline().addLast(LOGGING_HANDLER);
                    ch.pipeline().addLast(MESSAGE_CODEC);
                    ch.pipeline().addLast(RPC_HANDLER);

                }
            });
            Channel channel = serverBootstrap.bind(8080).sync().channel();
            RpcResponseMessage response = new RpcResponseMessage();
            response.setSequenceId(101);
            channel.writeAndFlush(response);
            channel.closeFuture().sync();
        } catch (InterruptedException e) {
            log.error("server error", e);
        } finally {
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }
    }

    public void autoRegister(){
        String applicationClassTrace = PackageScanUtils.getStackTrace();
        Class<?> clazz = null;
        try {
            clazz = Class.forName(applicationClassTrace);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            throw new RuntimeException("启动类未找到");
        }
        if (!clazz.isAnnotationPresent(RpcServerScan.class)) {
            throw new RuntimeException("启动类缺少@RpcServerScan注解");
        }
        String parentTrace = applicationClassTrace.substring(0, applicationClassTrace.lastIndexOf("."));
        Set<Class<?>> classes = PackageScanUtils.getClasses(parentTrace);
        for(Class<?> c : classes){
            //如果被@RpcServer注解修饰，就进行注册
            if (c.isAnnotationPresent(RpcServer.class)) {
                String serviceName = c.getAnnotation(RpcServer.class).name();
                if("".equals(serviceName)){
                    serviceName = c.getCanonicalName();
                }
                addServer(serviceName);
            }
        }



    }

    public void addServer(String name){
        nacosServerRegistry.register(name, new InetSocketAddress(ip, port));
    }
}
